package com.xs.ai.controller;

import com.xs.ai.services.LoggingAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.LocalDate;


/**
 * @author xushu
 * @version 1.0
 * @description:
 */
@RestController
//@CrossOrigin
public class OpenAiController {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public OpenAiController(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory, VectorStore vectorStore) {
        this.chatClient = chatClientBuilder.defaultSystem(
                        """
                        您是“Tuling”航空公司的客户聊天支持代理。请以友好、乐于助人且愉快的方式来回复。
                        您正在通过在线聊天系统与客户互动。 
                        在提供有关预订或取消预订的信息之前，您必须始终
                        从用户处获取以下信息：客户姓名、预定号。
                        在询问用户之前，请检查消息历史记录以获取此信息。
                        
                        重要：在执行任何修改或取消操作之前，必须明确告知用户操作的详细信息，并获得用户的明确确认。
                        具体流程如下：
                        1. 查询并显示当前预订详情
                        2. 明确告知用户即将进行的操作（修改或取消）
                        3. 详细说明操作的影响（如退款政策、新航班信息等）
                        4. 明确询问用户是否确认执行操作，例如："您确认要取消此预订吗？"或"您确认要修改此预订吗？"
                        5. 只有在用户明确回复"确认"、"是"或类似肯定答复后，才能执行操作
                        
                        请讲中文。
                        今天的日期是 {current_date}.
                        """
                )
                .defaultAdvisors(
                        new PromptChatMemoryAdvisor(chatMemory),
                        new LoggingAdvisor(vectorStore),
                        new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()
                                .withTopK(5)
                                .withSimilarityThreshold(0.7)) // RAG
                )
                .defaultFunctions("cancelBooking", "getBookingDetails", "changeBooking")
                .build();
        this.vectorStore = vectorStore;
    }

//    @CrossOrigin
    @GetMapping(value = "/ai/generateStreamAsString", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateStreamAsString(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
        Flux<String> content = this.chatClient.prompt()
                .user(message)
                .system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDate.now().toString()))
                .advisors(advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.query(message).withTopK(5).withSimilarityThreshold(0.5)))
                .stream()
                .content();
        return content.concatWith(Flux.just("[complete]"));
    }


}
